package com.asiainfo.complier.editor;

import com.asiainfo.complier.helper.JavaOutLineHelper;
import com.asiainfo.complier.helper.StringHelper;

import javax.swing.text.BadLocationException;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;
import java.awt.*;
import java.util.ArrayList;
import java.util.Stack;

public class CaretHighter implements Highlighter.HighlightPainter {

	private ArrayList<Object> highterList;
	private LineEditor editor;
	private int curDor;

	public void removeAllHighter() {

		for (Object highterObject : highterList) {
			editor.getHighlighter().removeHighlight(highterObject);
		}
		highterList.clear();

	}

	public void addWordHighter() {
		String allText = getText();
		allText=JavaOutLineHelper.clearString(allText);

		int pos = editor.getCaret().getDot();
		int dot = searchCratPair(pos, allText);
		if (dot >= 0) {
			try {
				Object highterObject = editor.getHighlighter().addHighlight(
						dot, dot, this);
				highterList.add(highterObject);

				Object shighterObject = editor.getHighlighter().addHighlight(
						pos - 1, pos, this);
				highterList.add(shighterObject);
			} catch (BadLocationException e) {
				e.printStackTrace();
			}
		}

	}

	public CaretHighter(LineEditor editor) {
		highterList = new ArrayList<Object>();
		this.editor = editor;
		editor.getSelectionColor();
	}

	public void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c) {
		try {
			Rectangle rc = c.modelToView(p0);
			if (curDor > 0) {
				int startLine = editor.getLineOfOffset(curDor);
				if (startLine > 0) {
					int endLine = editor.getLineOfOffset(p0);
					if (startLine != endLine) {
						editor.setPaintLine(startLine, endLine);
					}
					g.setColor(Color.RED);
					g.drawRect(rc.x - 2, rc.y, 9, rc.height);
				}
			}
		} catch (Exception e) {

			e.printStackTrace();
		}

	}

	private boolean isForward = true;
	private char startChar = ' ';
	private char endChar = ' ';

	public String getText() {
		try {
			return editor.getDocument().getText(0,
					editor.getDocument().getLength());
		} catch (BadLocationException e) {

			e.printStackTrace();
		}
		return "";

	}

	private boolean getPair(int index) {
		String pairsString = "{}[]<>()";
		if (index - 1 < 0)
			return false;
		char s = getText().charAt(index - 1);
		if (s == ' ')
			return false;

		int size = pairsString.length();
		boolean isFind = false;
		int i = 0;
		for (i = 0; i < size; i++)
			if (pairsString.charAt(i) == s) {
				isFind = true;
				break;
			}
		if (isFind) {
			if (i % 2 == 0) {
				startChar = s;
				endChar = pairsString.charAt(i + 1);
				isForward = true;
			} else {
				startChar = s;
				endChar = pairsString.charAt(i - 1);
				isForward = false;
			}
		}
		return isFind;
	}

	private int searchCratPair(int dot, String allText) {

		if (StringHelper.isNullOrEmpty(allText))
			return -1;

		curDor = dot;
		if (dot < 0)
			return -1;
		int size = allText.length() - 1;
		if (size <= dot)
			return -1;
		boolean isFind = getPair(dot);

		if (isFind) {
			if (isForward) {
				dot++;
				if (dot >= size)
					return -1;
				Stack<Character> strStack = new Stack<Character>();
				strStack.push(startChar);
				while (dot < size) {
					char curChar = allText.charAt(dot);
					if (curChar == startChar)
						strStack.push(startChar);
					else if (curChar == endChar) {
						strStack.pop();
						if (strStack.isEmpty()) {
							return dot;
						}
					}
					dot++;
				}
				return -1;

			} else {
				dot -= 2;
				if (dot < 0)
					return -1;
				Stack<Character> strStack = new Stack<Character>();
				strStack.push(startChar);

				while (dot >= 0) {
					char curChar = allText.charAt(dot);
					if (curChar == startChar) {
						strStack.push(startChar);
					} else if (curChar == endChar) {
						strStack.pop();
						if (strStack.isEmpty()) {
							return dot;
						}
					}
					dot--;
				}
				return -1;
			}

		} else {
			return -1;
		}

	}
}
